package com.webshooter.systems;

import com.webshooter.ClientUpdater;
import com.webshooter.decoder.MouseDownCommand;
import com.webshooter.decoder.MouseUpCommand;
import com.webshooter.encoder.ShootEffect;
import com.webshooter.encoder.UpdateEntityEvent;
import com.webshooter.entity.Entity;
import com.webshooter.entity.Entity.GameLogicState;
import com.webshooter.entity.EntityContainer;
import com.webshooter.gamelogic.ShotCalc;
import com.webshooter.map.TileMap;
import com.webshooter.math.Vector;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.inject.Inject;

@Startup
@Singleton
public class CombatSystem {

    @Inject
    private ClientUpdater clientUpdater;
    @Inject
    private EntityContainer entityContainer;
    @Inject
    private TileMap tileMap;
    @Resource
    TimerService tservice;
    private final long updateInterval = 50;

    @PostConstruct
    public void init() {
        tservice.createIntervalTimer(updateInterval, updateInterval, new TimerConfig());
    }

    @Timeout
    public void timeout() throws InterruptedException {
        for (Entity entity : entityContainer.getAllEntities()) {
            update(entity);
        }
    }

    public void update(Entity entity) {

        if (entity.gameLogicState == Entity.GameLogicState.DEAD) {

            if (entity.deadTime > 90) {
                Vector pos = getRandomSpawnPosition();
                entity.pos.x = pos.x;
                entity.pos.y = pos.y;
                entity.angle = 0;
                entity.gameLogicState = Entity.GameLogicState.ALIVE;

                entity.hitpoints = 100;
            }
            entity.deadTime++;
        }

        if (entity.mouseOne) {
            shootEvent(entity);
        }

        clientUpdater.addEvent(new UpdateEntityEvent(entity));
    }

    public Vector getRandomSpawnPosition() {
        return tileMap.getRandomSpawnPosition();
    }

    public void mouseDown(MouseDownCommand command) {
        Entity entity = entityContainer.findEntityByName(command.getName());
        if (entity == null) {
            return;
        }

        switch (command.getmouseButton()) {
            case 0:
                entity.mouseOne = true;
                break;
            case 1:
                entity.mouseTwo = true;
                break;
            case 3:
                entity.mouseThree = true;
                break;
        }
    }

    public void mouseUp(MouseUpCommand command) {
        Entity entity = entityContainer.findEntityByName(command.getName());
        if (entity == null) {
            return;
        }

        switch (command.getmouseButton()) {
            case 0:
                entity.mouseOne = false;
                break;
            case 1:
                entity.mouseTwo = false;
                break;
            case 3:
                entity.mouseThree = false;
                break;
        }
    }

    public void shootEvent(Entity entity) {

        Date currentTime = new Date(); // Or whatever

        long deltaTime = currentTime.getTime() - entity.lastShoot.getTime();

        if (deltaTime < 100) {
            return;
        }

        entity.lastShoot.setTime(currentTime.getTime());

        if (entity.gameLogicState != Entity.GameLogicState.ALIVE) {
            return;
        }
        float streufactor = 0.0f;
        if (deltaTime < 200) {
            streufactor = 0.2f;
        }

        if (entity.moveBackward || entity.moveForward || entity.strafeLeft || entity.strafeRight) {
            streufactor += 0.2f;
        }
        float random = (float) Math.random();
        float weaponAngleModifier = (random * streufactor) - (streufactor / 2);

        float shootAngle = entity.angle + weaponAngleModifier;

        ShotCalc shotCalc = new ShotCalc(tileMap);
        Vector end = shotCalc.calcShot(entity, shootAngle);

        List<Entity> getroffeneEnemies = shotCalc.calcEntitiesHitByShot(end, entity, entityContainer.getAllEntities());

        for (Entity getroffenerEnemy : getroffeneEnemies) {
            getroffenerEnemy.hitpoints -= 20;
            if (getroffenerEnemy.hitpoints <= 0) {
                getroffenerEnemy.gameLogicState = GameLogicState.DEAD;
            }
        }
        final ShootEffect shootEffect = new ShootEffect(entity, end);
        shootEffect.start = new Vector();
        shootEffect.start.x = shootEffect.entity.pos.x + (float) (50 * Math.cos(shootAngle));
        shootEffect.start.y = shootEffect.entity.pos.y + (float) (50 * Math.sin(shootAngle));

        shootEffect.end.x = shootEffect.entity.pos.x + shootEffect.end.x;
        shootEffect.end.y = shootEffect.entity.pos.y + shootEffect.end.y;
        shootEffect.angle = shootAngle;
        shootEffect.name = entity.name;
        shootEffect.weaponAngleModifier = weaponAngleModifier;

        clientUpdater.addEvent(shootEffect);
    }
}
